package com.atjava.nebula.core.exception.support;

import java.io.PrintWriter;
import java.io.StringWriter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.atjava.nebula.core.exception.baseExp.BaseAppException;
import com.atjava.nebula.core.exception.bean.ExceptionInfo;


/**
 * 异常相关的一些工具方法
 */
public class ExceptionUtil {

    /**
     * 日志类型:错误
     */
    public static final String LOGTYPE_ERROR = "error";

    /**
     * 日志类型:警告
     */
    public static final String LOGTYPE_DEBUG = "debug";

    /**
     * 日志类型:INFO
     */
    public static final String LOGTYPE_INFO = "info";

    /**
     * 日志类型:不记录
     */
    public static final String LOGTYPE_NOLOG = "nologging";

    /**
     * 指定长度后的异常信息将被忽略
     */
    public static final int EXCEPTION_TRACE_LENGTH = 4000;

    private static final String SEP = System.getProperty("line.separator") ;

    /**
     * StringBuffer的缓冲区初始大小
     * */
    private static final int INIT_BUFFER_SIZE = 1024;

    /**
     * 获取继承BaseAppException异常跟踪信息
     */
    public static String getDetailedMessage(BaseAppException exception) {
    	
        StringBuffer msg = new StringBuffer(INIT_BUFFER_SIZE);

        if (exception.getMessage() != null) {
            msg.append(exception.getMessage());
        }
        msg.append(SEP);

        //如果ExceptionInfo.isExpDebug为true,表示调试状态,此时log4j记录异常跟踪信息
        //如果ExceptionInfo.isExpDebug为false,表示发布状态,此时log4j不记录异常跟踪信息
        if(!ExceptionInfo.isExpDebug) {
        	return msg.toString() ;
        }
        
        //下面的信息为错误跟踪信息,为非友好信息,只用于调试阶段
        msg.append("Exception Stack Trace: ").append(SEP).append("Caused by: ");
        try {
            StringWriter sw = new StringWriter(INIT_BUFFER_SIZE);
            PrintWriter pw = new PrintWriter(sw);
            exception.printStackTrace(pw);
            msg.append(sw.toString());
            sw.close();
        } catch (Exception e) {
            msg.append(exception.toString());
        }
//        Throwable rootCause = exception.getCause();
//        if (rootCause != null) {
//            msg.append(SEP).append("Root Exception Stack Trace: ");
//            msg.append(rootCause.toString());
//            msg.append(SEP);
//            try {
//                StringWriter sw = new StringWriter(INIT_BUFFER_SIZE);
//                PrintWriter pw = new PrintWriter(sw);
//                rootCause.printStackTrace(pw);
//                msg.append(sw.toString());
//                sw.close();
//            } catch (Exception e) {
//                msg.append(rootCause.toString());
//            }
//        }
        return msg.toString();
    }

    /**
     * 获取继承Throwable异常跟踪信息
     */
    public static String getDetailedMessage(Throwable a) {
        StringBuffer msg = new StringBuffer();
       
        if (a.getMessage() != null) {
            msg.append(a.getMessage());
        }
        msg.append(SEP);
        
        //如果ExceptionInfo.isExpDebug为true,表示调试状态,此时log4j记录异常跟踪信息
        //如果ExceptionInfo.isExpDebug为false,表示发布状态,此时log4j不记录异常跟踪信息
        if(!ExceptionInfo.isExpDebug) {
        	return msg.toString() ;
        }
        
        msg.append("Exception Stack Trace: ").append(SEP).append("Caused by: ");;
        try {
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            a.printStackTrace(pw);
            msg.append(sw.toString());
            sw.close();
        } catch (Exception e) {
            msg.append(a.toString());
        }
        
//        Throwable rootCause = a.getCause();
//        if (rootCause != null) {
//            msg.append(SEP).append("Root Exception Stack Trace: ");
//            msg.append(rootCause.toString());
//            msg.append(SEP);
//            try {
//                StringWriter sw = new StringWriter(INIT_BUFFER_SIZE);
//                PrintWriter pw = new PrintWriter(sw);
//                rootCause.printStackTrace(pw);
//                msg.append(sw.toString());
//                sw.close();
//            } catch (Exception e) {
//                msg.append(rootCause.toString());
//            }
//        }
        String ret = msg.toString();
        msg = null;
        return ret;
    }

    /**
     * 获取继承Throwable实例的类名称
     * 类名称被当作错误号
     */
    public static String getClassName(Throwable e) {
    	
        String className = e.getClass().getName();
        String errId = className;

        if (e instanceof BaseAppException) {
            int i = className.lastIndexOf('.');
            errId = className.substring(i + 1);
        }
        return errId;
    }

    /**
     * 获取BaseAppException的详细异常信息, 包括
     */
    public static String getExceptionLog(Throwable exp) {
        String errorId = getClassName(exp);
        String detailedMessage = null;
        String exceptionMsg;
        if (exp instanceof BaseAppException) {
            BaseAppException ie = (BaseAppException) exp;
            detailedMessage = getDetailedMessage(ie);
            exceptionMsg = ie.getMessage();
        } else {
            detailedMessage = getDetailedMessage(exp);
            exceptionMsg = exp.getMessage();
        }
        
        StringBuffer lBuffer = new StringBuffer(INIT_BUFFER_SIZE);

        lBuffer.append(SEP).append("Exception Class: ");
        lBuffer.append(errorId);
        lBuffer.append(SEP);

        lBuffer.append("EXCEPTION MESSAGE: ");
        //lBuffer.append(detailedMessage);
        lBuffer.append(exceptionMsg);
        lBuffer.append(SEP);
        lBuffer.append("------------------------------------------------------------------").append(SEP);


        return lBuffer.toString();
    }

    /**
     * 从缓存中得到一个ExceptionInfo对象,通过异常exp的名字获得
     * */
    public static ExceptionInfo getExceptionInfo(Throwable exp) {
        
        ExceptionInfoCache ecache = ExceptionInfoCache.getInstance();
        ExceptionInfo exInfo = ecache.getExceptionInfo(ExceptionUtil.getClassName(exp));       
        return exInfo;
    }

    /**
     * 用Log4j记录日志
     */
    public static void logException(Class clazz, Throwable th, String loggingType) {
    	
    	//MyResource myres=new MyResource("WEB-INF/config/log/log4j.properties");
		//PropertyConfigurator.configure(myres.getURL());
        Logger logger = LoggerFactory.getLogger(clazz);//Logger.getLogger(clazz);

        //String exceptionTrace = ExceptionUtil.getExceptionLog(th);
        String exceptionTrace = th.getMessage();
        

        //exception.printStackTrace(pw);
        
        if (ExceptionUtil.LOGTYPE_NOLOG.equals(loggingType))
            return;
        else if (ExceptionUtil.LOGTYPE_ERROR.equals(loggingType))
            logger.error(exceptionTrace,th);
        else if (ExceptionUtil.LOGTYPE_INFO.equals(loggingType))
            logger.info(exceptionTrace,th);
        else if (ExceptionUtil.LOGTYPE_DEBUG.equals(loggingType))
            logger.debug(exceptionTrace,th);
        else {
            logger.error(exceptionTrace,th);
        }
    }

    /**
     * 用Log4j记录日志,默认为错误级别
     *  
     */
    public static void logException(Class clazz, Throwable th) {
        logException(clazz, th, LOGTYPE_ERROR);
    }
}